<template>
  <div>
   
    <!-- 搜索栏 -->
    <div style="display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:12px">
      <div style="display:flex; align-items:center; gap:8px">
        <el-input
          v-model="searchQuery"
          placeholder="请输入【用户名/昵称/所属医院/角色】搜索"
          clearable
          @clear="clearSearch"
          style="width:360px"
        />
      </div>

      <div>
        <el-button type="primary" @click="openAdd" v-if="canAdd">新增用户</el-button>
      </div>
    </div>

    <el-table :data="users" stripe border style="width:100%" remote @sort-change="onSortChange" @header-click="onHeaderClick">
      <el-table-column label="序号" width="80">
        <template #default="{ $index }">{{ (page - 1) * pageSize + $index + 1 }}</template>
      </el-table-column>
      <el-table-column prop="user_name" label="用户名" sortable />
      <el-table-column prop="alisa" label="昵称" sortable />
      <el-table-column prop="role_id" label="角色" sortable>
        <template #default="{ row }">{{ roleName(row.role_id) }}</template>
      </el-table-column>
      <el-table-column prop="hospital_name" label="所属医院" sortable />
      <el-table-column label="操作" width="210">
        <template #default="{ row }">
          <el-button size="small" @click="openEdit(row)" v-if="canEdit">编辑</el-button>
          <el-button size="small" type="warning" @click="resetPassword(row)" style="margin-left:8px" v-if="canEdit">重置密码</el-button>
          <el-button size="small" type="danger" @click="remove(row)" style="margin-left:8px" v-if="canDelete">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <div style="margin-top:12px; display:flex; justify-content:flex-end; align-items:center">
      
      <el-pagination
        background
        layout="total, sizes, prev, pager, next"
        :current-page="page"
        :page-size="pageSize"
        :page-sizes="[5,10,20]"
        :total="total"
        @current-change="gotoPage"
        @size-change="onSizeChange"
      />
    </div>

    <el-alert v-if="error" type="error" :title="error" show-icon style="margin-top:12px" />

    <!-- Dialog form -->
    <el-dialog :title="editing.id ? '编辑用户' : '新增用户'" v-model="showModal" width="520px">
      <el-form ref="formRef" :model="editing" :rules="rules" label-width="100px">
        <el-form-item prop="user_name">
          <template #label>
             用户名
          </template>
          <el-input v-model="editing.user_name" :disabled="!!editing.id" />
        </el-form-item>

        <!-- <el-form-item label="密码">
          <el-input v-model="editing.password" type="password" :disabled="!!editing.id"  />
        </el-form-item> -->

        <el-form-item prop="alisa">
          <template #label>
             昵称
          </template>
          <el-input v-model="editing.alisa" />
        </el-form-item>

        <el-form-item prop="role_id">
          <template #label>
            角色
          </template>
          <el-select v-model.number="editing.role_id" placeholder="选择角色">
            <el-option v-for="r in roles" :key="r.id" :label="r.role_name || r.name" :value="r.id" />
          </el-select>
        </el-form-item>
       
        <el-form-item label="所属医院">
          <el-select v-model.number="editing.hospital_id" placeholder="选择所属医院" filterable clearable :disabled="isAdminSelected">
            <!-- prefer common hospital name fields from backend so the select shows name instead of id -->
            <el-option v-for="h in hospitals" :key="h.id" :label="h.hos_name" :value="h.id" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <div style="text-align:left; color:chocolate">
            提示1：带<span style="color:red">*</span> 字段为必填~
          </div>
        </el-form-item>
        <el-form-item>
          <div style="text-align:left; color:chocolate">
            提示2：系统管理员不能选择医院~
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="closeModal">取消</el-button>
        <el-button type="primary" @click="submit" :disabled="!canAdd && !canEdit">保存</el-button>
      </template>

    </el-dialog>

  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, reactive, computed, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useAuthStore } from '../stores/auth'

const auth = useAuthStore()
// permission flags for this page
const canAdd = computed(() => auth.hasPermission('0101', '新增'))
const canEdit = computed(() => auth.hasPermission('0101', '编辑'))
const canDelete = computed(() => auth.hasPermission('0101', '删除'))
const users = ref<any[]>([])
const roles = ref<any[]>([])
const hospitals = ref<any[]>([])
const error = ref('')

// search
const searchQuery = ref('')
const searchTimer = ref<number | null>(null)

// pagination
const page = ref(1)
const pageSize = ref(10)
const total = ref(0)
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))

// sorting (server-side)
const sortBy = ref<string | null>(null)
const sortOrder = ref<'asc' | 'desc' | null>(null)

const showModal = ref(false)
const editing = reactive<any>({ id: null, user_name: '', password: '', role_id: null, alisa: '', hospital_id: null, leave_date: '' })
const formRef = ref<any>(null)

const rules = {
  user_name: [{ required: true, message: '请输入用户名', trigger: ['blur', 'change'] }],
  alisa: [{ required: true, message: '请输入昵称', trigger: ['blur', 'change'] }],
  role_id: [{ required: true, message: '请选择角色', trigger: ['change'] }]
}

// new: computed flag to detect admin/system-admin role and disable hospital select
const isAdminSelected = computed(() => {
  const rid = editing.role_id
  if (!rid) return false
  const r = roles.value.find((x: any) => x.id === rid)
  const name = (r && (r.role_name || r.name)) || ''
  // treat roles named 'admin' or containing '管理员'/'系统管理员' as system admin
  return /admin|管理员|系统管理员/i.test(String(name))
})

// when admin role is selected, clear hospital_id to avoid confusing state
watch(isAdminSelected, (val) => {
  if (val) editing.hospital_id = null
})

function roleName(id: number) {
  const r = roles.value.find((x: any) => x.id === id)
  return r ? (r.role_name || r.name) : ''
}

async function load() {
  error.value = ''
  await loadRoles()
  await loadHospitals()
  try {
    // If either sorting or searching is requested, fetch the full dataset and filter/sort locally.
    if (sortBy.value || (searchQuery.value && String(searchQuery.value).trim() !== '')) {
      const params = new URLSearchParams()
      // request a very large limit to try to retrieve all records; backend should handle it or return all
      params.set('limit', '1000000')
      const res = await auth.apiFetch(`/users?${params.toString()}`)
      const all = (res.users || res || []).map((u: any) => ({ ...u }))

      // apply search filter if present (case-insensitive match against common string fields)
      const q = String(searchQuery.value || '').trim().toLowerCase()
      let filtered = all
      if (q) {
        filtered = all.filter((u: any) => {
          // gather candidates: username, nickname, hospital name, role name
          const uname = String(u.user_name || u.username || '').toLowerCase()
          const alisa = String(u.alisa || '').toLowerCase()
          const hname = String(u.hospital_name || u.hos_name || u.name || '').toLowerCase()
          // try to resolve role name from roles list
          const r = roles.value.find((x: any) => x.id === u.role_id)
          const rname = String((r && (r.role_name || r.name)) || '').toLowerCase()
          return uname.includes(q) || alisa.includes(q) || hname.includes(q) || rname.includes(q)
        })
      }

      const prop = sortBy.value
      const order = sortOrder.value === 'asc' ? 1 : -1

      // sort the filtered list only if a prop is provided
      if (prop) {
        filtered.sort((a: any, b: any) => {
          const va = a[prop] ?? ''
          const vb = b[prop] ?? ''
          if (typeof va === 'number' && typeof vb === 'number') return (va - vb) * order
          const sa = String(va).toLowerCase()
          const sb = String(vb).toLowerCase()
          if (sa < sb) return -1 * order
          if (sa > sb) return 1 * order
          return 0
        })
      }

      total.value = filtered.length
      users.value = filtered.slice((page.value - 1) * pageSize.value, page.value * pageSize.value)
    } else {
      const params = new URLSearchParams()
      params.set('page', String(page.value))
      params.set('limit', String(pageSize.value))
      if (sortBy.value) params.set('sort_by', sortBy.value)
      if (sortOrder.value) params.set('sort_order', sortOrder.value)

      const res = await auth.apiFetch(`/users?${params.toString()}`)
      // expect { users: [...], total: number }
      // normalize backend keys if needed
      users.value = (res.users || res || []).map((u: any) => ({ ...u }))
      total.value = typeof res.total === 'number' ? res.total : users.value.length
    }
  } catch (e) {
    // fallback mock
    users.value = [
      { id: 1, user_name: 'admin', alisa: '管理员', role_id: 1, hospital_id: 1, hospital_name: '示例医院A', entry_date: '2020-01-01' },
      { id: 2, user_name: 'user', alisa: '普通用户', role_id: 2, hospital_id: 2, hospital_name: '示例医院B', entry_date: '2021-06-01' }
    ].slice((page.value - 1) * pageSize.value, page.value * pageSize.value)
    total.value = 2
  }
}

async function loadRoles() {
  try {
    const rres = await auth.apiFetch('/roles')
    roles.value = rres.roles || rres || []
  } catch (e) {
    roles.value = [{ id: 1, role_name: 'admin' }, { id: 2, role_name: 'user' }]
  }
}

async function loadHospitals() {
  try {
    const hres = await auth.apiFetch('/hospitals')
    hospitals.value = hres.hospitals || hres || []
  } catch (e) {
    hospitals.value = [{ id: 1, hos_name: '示例医院A' }, { id: 2, hos_name: '示例医院B' }]
  }
}

onMounted(async () => {
  await loadRoles()
  await load()
})

async function openAdd() {
  if (!canAdd.value) { ElMessage.warning('没有新增权限'); return }
  await loadRoles()
  await loadHospitals()
  editing.id = null
  editing.user_name = ''
  // set initial password to the agreed default
  editing.password = 'Jsws123456'
  editing.role_id =  null
  editing.alisa = ''
  editing.hospital_id = null
  editing.leave_date = ''
  showModal.value = true  
}

async function openEdit(u: any) {
  if (!canEdit.value) { ElMessage.warning('没有编辑权限'); return }
  await loadRoles()
  await loadHospitals()
  editing.id = u.id
  editing.user_name = u.user_name || u.username || ''
  editing.password = ''
  editing.role_id = u.role_id
  editing.alisa = u.alisa || ''
  // prefer explicit hospital_id; if missing but a hospital name is present on the user row,
  // try to find the corresponding hospital id so the select shows the hospital name instead of the raw id
  editing.hospital_id = u.hospital_id ?? (u.hospital_name ? (hospitals.value.find((h: any) => (h.hos_name === u.hospital_name || h.name === u.hospital_name || h.hospital_name === u.hospital_name))?.id ?? null) : null)
  editing.leave_date = u.leave_date || ''
  showModal.value = true
}

function closeModal() {
  showModal.value = false
}

async function submit() {
  error.value = ''
  try {
    // validate required fields via el-form rules
    if (formRef.value) {
      await formRef.value.validate()
    } else {
      // fallback validation
      if (!editing.user_name || !editing.alisa || !editing.role_id) {
        error.value = '请填写所有必填字段'
        ElMessage.error(error.value)
        return
      }
    }
    // permission guard before submitting
    if (editing.id && !canEdit.value) { ElMessage.error('没有编辑权限'); return }
    if (!editing.id && !canAdd.value) { ElMessage.error('没有新增权限'); return }
    if (editing.id) {
      const payload: any = { role_id: editing.role_id, alisa: editing.alisa, hospital_id: editing.hospital_id, leave_date: editing.leave_date }
      if (editing.password) payload.pwd = editing.password
      await auth.apiFetch(`/users/${editing.id}`, { method: 'PUT', body: JSON.stringify(payload) })
      ElMessage.success('编辑成功')
    } else {
      // form validation already ensures username, nickname and role are present
      // ensure initial password is used when none provided
      const payload = { user_name: editing.user_name, pwd: editing.password || 'Jsws123456', role_id: editing.role_id, alisa: editing.alisa, hospital_id: editing.hospital_id, leave_date: editing.leave_date }
      await auth.apiFetch(`/users`, { method: 'POST', body: JSON.stringify(payload) })
      ElMessage.success('新增成功')
    }
    closeModal()
    await load()
  } catch (e: any) {
    try { const body = await e.json(); error.value = body.message || '操作失败' } catch { error.value = '操作失败' }
    ElMessage.error(error.value)
  }
}

async function remove(u: any) {
  error.value = ''
  if (!canDelete.value) { ElMessage.warning('没有删除权限'); return }
  ElMessageBox.confirm(`确定删除用户 ${u.user_name || u.username} ?`, '删除确认', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      try {
        await auth.apiFetch(`/users/${u.id}`, { method: 'DELETE' })
        ElMessage.success('删除成功')
        if (users.value.length === 1 && page.value > 1) {
          page.value = page.value - 1
        }
        await load()
      } catch (e: any) {
        try { const body = await e.json(); error.value = body.message || '删除失败' } catch { error.value = '删除失败' }
        ElMessage.error(error.value)
      }
    })
    .catch(() => {
      // 用户取消，不做任何操作
    })
}

// 新增：重置密码为固定初始密码 jsws123456
async function resetPassword(u: any) {
  error.value = ''
  const uname = u.user_name || u.username || ''
  const msg = `确认把用户名为${uname}的密码重置为初始密码 Jsws123456 吗？`
  ElMessageBox.confirm(msg, '重置确认', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      try {
        // backend accepts pwd field in PUT /users/:id
        await auth.apiFetch(`/users/${u.id}`, { method: 'PUT', body: JSON.stringify({ pwd: 'Jsws123456' }) })
        ElMessage.success('重置成功')
        await load()
      } catch (e: any) {
        try { const body = await e.json(); error.value = body.message || '重置失败' } catch { error.value = '重置失败' }
        ElMessage.error(error.value)
      }
    })
    .catch(() => {
      // 用户取消
    })
}

function gotoPage(n: number) {
  if (n < 1) n = 1
  if (n > totalPages.value) n = totalPages.value
  page.value = n
  load()
}

// handle page size changes properly
function onSizeChange(size: number) {
  pageSize.value = size
  gotoPage(1)
}

// handle table header sort-change from Element Plus
function onSortChange(sort: any) {
  // debug: log the sort payload to inspect structure when user clicks
  console.log('onSortChange payload:', sort)

  // sort may contain { column, prop, order } depending on Element Plus version
  const column = sort && sort.column ? sort.column : null
  const prop = sort && sort.prop ? sort.prop : (column ? (column.property ?? column.prop ?? null) : null)
  const orderRaw = sort && sort.order ? sort.order : null

  // order may be 'ascending'|'descending' or 'asc'|'desc' depending on source
  let order: string | null = null
  if (orderRaw) {
    order = (orderRaw === 'ascending' || orderRaw === 'asc') ? 'asc' : 'desc'
  } else if (prop && prop === sortBy.value) {
    // Fallback: some Element Plus builds may emit incomplete payloads when toggling the same column.
    // If order is missing but the user clicked the current sorted column, toggle previous order.
    if (sortOrder.value === 'asc') order = 'desc'
    else if (sortOrder.value === 'desc') order = null
    else order = 'asc'
  }

  if (!prop || !order) {
    // if order is null we clear sorting
    sortBy.value = null
    sortOrder.value = null
  } else {
    sortBy.value = String(prop)
    sortOrder.value = order as 'asc' | 'desc'
  }

  // when sorting changes, go back to first page
  page.value = 1
  // call load to fetch sorted data
  load()
}

// handle header click to reliably toggle sorting for a column
function onHeaderClick(column: any) {
  if (!column) return
  // determine prop name from column definition
  const prop = column.property ?? column.prop ?? null
  if (!prop) return

  // only act on sortable columns
  if (!column.sortable && column.sortable !== 'custom' && column.sortable !== true) return

  // cycle: null -> asc -> desc -> null
  if (sortBy.value !== prop) {
    sortBy.value = String(prop)
    sortOrder.value = 'asc'
  } else {
    if (sortOrder.value === 'asc') sortOrder.value = 'desc'
    else if (sortOrder.value === 'desc') { sortBy.value = null; sortOrder.value = null }
    else sortOrder.value = 'asc'
  }

  page.value = 1
  load()
}

function clearSearch() {
  // always show all when cleared
  searchQuery.value = ''
  page.value = 1
  load()
}

// watch searchQuery and perform a debounced automatic search
watch(searchQuery, () => {
  if (searchTimer.value) clearTimeout(searchTimer.value)
  // debounce 350ms
  searchTimer.value = window.setTimeout(() => {
    page.value = 1
    load()
  }, 350)
})

function applySearch() {
  // kept for backward compatibility (e.g. if called elsewhere)
  page.value = 1
  load()
}
</script>

<style scoped>
/* minimal adjustments for Element Plus */
</style>